﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

public class CommolOption
{

    //public static T Create<T>() where T:class
    //{
    //    return Activator.CreateInstance(typeof(T),BindingFlags.Instance|)
    //}

    public static void Switch<T>(T a, T b)
    {
        T t = a;
        a = b;
        b = t;
    }

    public static void Switch<T>(ref T a, ref T b)
    {
        T t = a;
        a = b;
        b = t;
    }

    public static void Switch<T, V>(V source, int x, int y) where V : IList<T>
    {
        T t = source[x];
        source[x] = source[y];
        source[y] = t;
    }

    public static void Switch<T, V>(V sourceX, int x, V sourceY, int y) where V : IList<T>
    {
        T t = sourceX[x];
        sourceX[x] = sourceY[y];
        sourceY[y] = t;
    }

    public static void SwitchWhen<T>(ref T a, ref T b, Func<T, T, bool> compare)
    {
        if (compare.Invoke(a, b))
        {
            Switch<T>(ref a, ref b);
        }
    }

    public static string ShowAssemblyTypes(System.Reflection.Assembly asmb)
    {
        StringBuilder sb = new();

        foreach (Type type in asmb.GetTypes())
        {
            sb.AppendFormat($"[TypeName]: {type.Name} [BaseType]: {type.BaseType} \n");
        }
        return sb.ToString();
    }

    public static string ShowAssemblyTypes(System.Reflection.Assembly asmb, Type baseType)
    {
        StringBuilder sb = new();

        foreach (Type type in asmb.GetTypes())
        {
            if (baseType == type.BaseType)
                sb.AppendFormat($"[TypeName]: {type.Name} [BaseType]: {type.BaseType} \n");
        }
        return sb.ToString();
    }

    public static string ShowTypeMethods(Type type)
    {
        StringBuilder sb = new();

        foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
        {
            sb.AppendFormat($"[Method]: {method.Name} [ReturnType]: {method.ReturnType} [IsPrivate]: {method.IsPrivate}\n");
        }
        return sb.ToString();
    }

    public static Type[] GetAttributeTypes<T>(Assembly asmb) where T : Attribute
    {
        List<Type> types = new();
        Type baseAb = typeof(T);
        foreach (Type type in asmb.GetTypes())
        {
            foreach (var ab in type.GetCustomAttributes(false))
            {
                if (ab.GetType() == baseAb)
                {
                    types.Add(type);
                }
            }
        }

        return types.ToArray();
    }


    public static MethodInfo GetAnyMethod(Type type, string methodName)
    {
        return type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    }

    public static T CreateDelegate<T>(object obj, MethodInfo method) where T : Delegate
    {
        return method.CreateDelegate(typeof(T), obj) as T;
    }

    public static bool TryCreateDelegate<T>(object obj, string methodName, out T t) where T : Delegate
    {
        MethodInfo method = GetAnyMethod(obj.GetType(), methodName);
        t = null;

        if (method == null)
            return false;

        t = method.CreateDelegate(typeof(T), obj) as T;
        return true;
    }

}
